package com.autoagent.ai_live_master.common.utils;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.autoagent.ai_live_master.common.config.VoiceProcessConfig;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


/**
 * 智能语音处理工具类
 * 提供文件语音识别功能，由Spring容器管理
 */
@Slf4j
@Component
public class VoiceProcessUtil {
    // 请求参数常量
    private static final String KEY_APP_KEY = "appkey";
    private static final String KEY_FILE_LINK = "file_link";
    private static final String KEY_VERSION = "version";
    private static final String KEY_ENABLE_WORDS = "enable_words";
    private static final String KEY_ENABLE_SAMPLE_RATE_ADAPTIVE = "enable_sample_rate_adaptive";
    
    // 响应参数常量
    private static final String KEY_TASK = "Task";
    private static final String KEY_TASK_ID = "TaskId";
    private static final String KEY_STATUS_TEXT = "StatusText";
    private static final String KEY_RESULT = "Result";
    
    // 状态值常量
    private static final String STATUS_SUCCESS = "SUCCESS";
    private static final String STATUS_RUNNING = "RUNNING";
    private static final String STATUS_QUEUEING = "QUEUEING";
    
    // 请求动作常量
    private static final String POST_REQUEST_ACTION = "SubmitTask";
    private static final String GET_REQUEST_ACTION = "GetTaskResult";
    
    // 阿里云鉴权客户端
    private IAcsClient client;
    
    // 配置信息
    @Autowired
    private VoiceProcessConfig config;
    
    /**
     * 初始化客户端
     * 使用@PostConstruct注解标注的方法会在依赖注入完成后自动调用
     */
    @PostConstruct
    private void init() {
        // 设置endpoint
        try {
            DefaultProfile.addEndpoint(config.getEndpointName(), config.getRegionId(), 
                    config.getProduct(), config.getDomain());
        } catch (ClientException e) {
            log.error("设置endpoint失败", e);
        }
        
        // 创建DefaultAcsClient实例并初始化
        DefaultProfile profile = DefaultProfile.getProfile(config.getRegionId(), 
                config.getAccessKeyId(), config.getAccessKeySecret());
        this.client = new DefaultAcsClient(profile);
    }
    
    /**
     * 处理语音文件并返回识别结果
     * @param fileLink 文件链接
     * @return 识别结果文本
     * @throws IllegalArgumentException 当文件链接为空或只包含空格时抛出
     */
    public String processVoiceFile(String fileLink) {
        // 验证文件链接参数
        if (fileLink == null || fileLink.trim().isEmpty()) {
            log.error("文件链接为空或无效");
            throw new IllegalArgumentException("文件链接不能为空");
        }
        
        // 提交录音文件识别请求，获取任务ID
        String taskId = submitFileTransRequest(fileLink);
        if (taskId == null) {
            log.error("录音文件识别请求失败");
            return null;
        }
        
        log.info("录音文件识别请求成功，task_id: {}", taskId);
        
        // 根据任务ID获取识别结果
        return getFileTransResult(taskId);
    }
    
    /**
     * 提交文件转写请求
     * @param fileLink 文件链接
     * @return 任务ID
     */
    private String submitFileTransRequest(String fileLink) {
        // 创建CommonRequest，设置请求参数
        CommonRequest postRequest = new CommonRequest();
        postRequest.setDomain(config.getDomain());
        postRequest.setVersion(config.getApiVersion());
        postRequest.setAction(POST_REQUEST_ACTION);
        postRequest.setProduct(config.getProduct());
        
        // 设置录音文件识别请求参数，以JSON字符串的格式设置到请求Body中
        JSONObject taskObject = new JSONObject();
        taskObject.put(KEY_APP_KEY, config.getAppKey());
        taskObject.put(KEY_FILE_LINK, fileLink);
        taskObject.put(KEY_VERSION, "4.0"); // 使用4.0版本
        taskObject.put(KEY_ENABLE_SAMPLE_RATE_ADAPTIVE, true);
        
        String task = taskObject.toJSONString();
        log.debug("提交的任务参数: {}", task);
        
        // 设置以上JSON字符串为Body参数
        postRequest.putBodyParameter(KEY_TASK, task);
        postRequest.setMethod(MethodType.POST);
        
        // 提交录音文件识别请求，获取录音文件识别请求任务的ID
        String taskId = null;
        try {
            CommonResponse postResponse = client.getCommonResponse(postRequest);
            log.debug("提交录音文件识别请求的响应：{}", postResponse.getData());
            
            if (postResponse.getHttpStatus() == 200) {
                JSONObject result = JSONObject.parseObject(postResponse.getData());
                String statusText = result.getString(KEY_STATUS_TEXT);
                if (STATUS_SUCCESS.equals(statusText)) {
                    taskId = result.getString(KEY_TASK_ID);
                }
            }
        } catch (ClientException e) {
            log.error("提交录音文件识别请求失败", e);
        }
        
        return taskId;
    }
    
    /**
     * 获取文件转写结果
     * @param taskId 任务ID
     * @return 识别结果
     */
    private String getFileTransResult(String taskId) {
        // 创建CommonRequest，设置任务ID
        CommonRequest getRequest = new CommonRequest();
        getRequest.setDomain(config.getDomain());
        getRequest.setVersion(config.getApiVersion());
        getRequest.setAction(GET_REQUEST_ACTION);
        getRequest.setProduct(config.getProduct());
        getRequest.putQueryParameter(KEY_TASK_ID, taskId);
        getRequest.setMethod(MethodType.GET);
        
        // 提交录音文件识别结果查询请求
        // 以轮询的方式进行识别结果的查询，直到服务端返回的状态描述为"SUCCESS"或错误描述，则结束轮询
        String result = null;
        while (true) {
            try {
                CommonResponse getResponse = client.getCommonResponse(getRequest);
                log.debug("识别查询结果：{}", getResponse.getData());
                
                if (getResponse.getHttpStatus() != 200) {
                    log.error("识别查询HTTP状态异常: {}", getResponse.getHttpStatus());
                    break;
                }
                
                JSONObject rootObj = JSONObject.parseObject(getResponse.getData());
                String statusText = rootObj.getString(KEY_STATUS_TEXT);
                
                if (STATUS_RUNNING.equals(statusText) || STATUS_QUEUEING.equals(statusText)) {
                    // 继续轮询，设置轮询时间间隔
                    log.info("任务正在处理中，状态: {}", statusText);
                    Thread.sleep(10000);
                } else {
                    // 状态信息为成功，返回识别结果；状态信息为异常，返回空
                    if (STATUS_SUCCESS.equals(statusText)) {
                        result = rootObj.getString(KEY_RESULT);
                        // 状态信息为成功，但没有识别结果，则可能是由于文件里全是静音、噪音等导致识别为空
                        if (result == null) {
                            log.warn("识别成功但结果为空，可能是文件中没有有效语音内容");
                            result = "";
                        }
                    } else {
                        log.error("识别失败，状态: {}", statusText);
                    }
                    break;
                }
            } catch (Exception e) {
                log.error("获取识别结果异常", e);
                break;
            }
        }
        try {
            log.info("开始解析 JSON 字符串...");
            ObjectMapper mapper = new ObjectMapper();
            JsonNode rootNode = mapper.readTree(result);

            log.info("获取 'Sentences' 数组节点...");
            JsonNode sentences = rootNode.get("Sentences");

            if (sentences == null || !sentences.isArray()) {
                log.error("'Sentences' 不是数组或为空！");
                return "";
            }

            log.info("遍历句子数组，提取文本...");
            StringBuilder fullText = new StringBuilder();

            int index = 0;
            for (JsonNode sentence : sentences) {
                String text = sentence.get("Text").asText();
                log.debug("第 {} 个句子文本: {}", ++index, text);
                fullText.append(text);
            }

            log.info("所有文本合并完成。");
            log.info("合并后的完整文本：{}", fullText);
            return fullText.toString();

        } catch (Exception e) {
            log.error("解析 JSON 发生异常！", e);
            return "";
        }
    }
}